package com.tarena.lbs.coupon.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.attach.pojo.dto.AttachQrDTO;
import com.tarena.lbs.attach.pojo.param.AttachQRParam;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.BasePageQuery;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.coupon.dao.repository.CouponCodeRepository;
import com.tarena.lbs.coupon.dao.repository.CouponRepository;
import com.tarena.lbs.coupon.dao.repository.StockRepository;
import com.tarena.lbs.coupon.dao.repository.UserCouponsRepository;
import com.tarena.lbs.coupon.enums.CouponStatusEnum;
import com.tarena.lbs.coupon.enums.UserCouponsStatusEnum;
import com.tarena.lbs.coupon.pojo.param.CouponParam;
import com.tarena.lbs.coupon.pojo.po.CouponPO;
import com.tarena.lbs.coupon.pojo.po.CouponStockPO;
import com.tarena.lbs.coupon.pojo.po.UserCouponsPO;
import com.tarena.lbs.coupon.pojo.query.UserCouponCodeQuery;
import com.tarena.lbs.coupon.pojo.query.UserCouponQuery;
import com.tarena.lbs.coupon.pojo.vo.CouponVO;
import com.tarena.lbs.coupon.pojo.vo.UserCouponsVO;
import com.tarena.lbs.coupon.service.CouponService;
import com.tarena.lbs.user.api.UserApi;
import com.tarena.lbs.user.api.pojo.dto.AdminDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class CouponServiceImpl implements CouponService {

    @DubboReference
    private UserApi userApi;

    @DubboReference
    private AttachApi attachApi;

    @Autowired
    private CouponRepository couponRepository;

    @Autowired
    private StockRepository stockRepository;

    @Autowired
    private CouponCodeRepository couponCodeRepository;

    @Autowired
    private UserCouponsRepository userCouponsRepository;

    /**
     * 查询当前商家发布的优惠券分页列表
     * @param pageQuery 分页参数
     * @return 封装好的PageResult对象
     * @throws BusinessException
     */
    @Override
    public PageResult<CouponVO> pageList(BasePageQuery pageQuery) throws BusinessException {
        log.debug("查询当前商家优惠券分页列表业务：pageQuery={}", pageQuery);
        //校验身份
//        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
//        Asserts.isTrue(userPrinciple==null,new BusinessException("401","身份校验失败"));
//
//        AdminDto admin = userApi.getAdminById(userPrinciple.getId());
//        Asserts.isTrue(admin.getAccountType()==0,new BusinessException("297","账号类型错误"));

//        PageInfo<CouponPO> couponPOPageInfo = couponRepository.getCouponListByBusinessId(pageQuery,admin.getBusinessId());
        Page<CouponPO> couponPOPage = couponRepository.getCouponListByBusinessId(pageQuery,1);
        List<CouponVO> couponVOS = new ArrayList<>();
        couponPOPage.getRecords().forEach(couponPO -> {
            CouponVO couponVO = new CouponVO();
            BeanUtils.copyProperties(couponPO,couponVO);
            couponVOS.add(couponVO);
        });
        PageResult<CouponVO> couponVOPageResult = new PageResult<>();
        couponVOPageResult.setObjects(couponVOS);
        couponVOPageResult.setPageNo((int)couponPOPage.getCurrent());
        couponVOPageResult.setPageSize((int)couponPOPage.getSize());
        couponVOPageResult.setTotal(couponPOPage.getTotal());
        return couponVOPageResult;
    }

    /**
     * 保存优惠券
     * @param couponParam 优惠券参数
     * @throws BusinessException
     */
    @Override
    public void saveCoupon(CouponParam couponParam) throws BusinessException {
        log.debug("保存优惠券业务：couponParam={}", couponParam);
        //身份校验
//        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
//        Asserts.isTrue(userPrinciple==null, new BusinessException("401","身份校验失败"));
//        //校验当前用户是否商家
//        AdminDto admin = userApi.getAdminById(userPrinciple.getId());
//        Asserts.isTrue(admin.getAccountType()!=1,new BusinessException("297","无操作权限"));
//        Asserts.isTrue(admin.getBusinessId()!=couponParam.getBusinessId(),new BusinessException("297","无操作权限"));
        couponParam.setBusinessId(1);
        //优惠券发行总量不能超过100w张
        Asserts.isTrue(couponParam.getMaxUsageLimit()>1000000,new BusinessException("296","优惠券发行总量不能超过100w张"));
        if (couponParam.getId() != null){
            //修改优惠券
            CouponPO coupon = new CouponPO();
            BeanUtils.copyProperties(couponParam,coupon);
            coupon.setUpdateAt(new Date());
            couponRepository.updateCoupon(coupon);
            //对比发行量 更新库存
            CouponPO couponPO = couponRepository.getCouponById(couponParam.getId());
            Asserts.isTrue(couponPO==null,new BusinessException("297","优惠券不存在"));
            int change = couponParam.getMaxUsageLimit() - couponPO.getMaxUsageLimit();
            CouponStockPO couponStockPO = stockRepository.selectByCouponId(couponPO.getId());
            Asserts.isTrue(couponStockPO==null,new BusinessException("297","优惠券库存不存在"));
            couponStockPO.setNum(couponStockPO.getNum() + change);
            stockRepository.saveStock(couponStockPO);
        }else {
            //新增优惠券
            CouponPO couponPO = new CouponPO();
            BeanUtils.copyProperties(couponParam, couponPO);
            couponPO.setStatus(CouponStatusEnum.ACTIVE.getCode());
            couponPO.setEnableStatus(1);
            couponPO.setCreateAt(new Date());
            couponRepository.insertCoupon(couponPO);
            //添加库存数据
            CouponStockPO couponStockPO = new CouponStockPO();
            couponStockPO.setNum(couponParam.getMaxUsageLimit());
            couponStockPO.setCouponId(couponPO.getId());
            couponStockPO.setBusinessId(couponParam.getBusinessId());
            couponStockPO.setCreateAt(new Date());
            stockRepository.saveStock(couponStockPO);
        }
    }


    @Override
    public CouponVO detail(Integer id) throws BusinessException {
        log.debug("查询优惠券详情业务：couponId={}", id);
        //身份校验
//        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
//        Asserts.isTrue(userPrinciple==null,new BusinessException("401","身份校验失败"));
        CouponPO couponPO = couponRepository.getCouponById(id);
        CouponVO couponVO = new CouponVO();
        BeanUtils.copyProperties(couponPO,couponVO);
        return couponVO;
    }

    @Override
    public PageResult<UserCouponsVO> receiveList(UserCouponQuery couponQuery) throws BusinessException {
        log.debug("用户领取优惠券列表业务：couponQuery={}", couponQuery);
        //身份校验
//        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
//        Asserts.isTrue(userPrinciple==null,new BusinessException("401","身份校验失败"));
        //查询页面
        Page<UserCouponsPO> userCouponsPOPage = userCouponsRepository.receiveList(couponQuery);
        PageResult<UserCouponsVO> userCouponsVOPageResult = new PageResult<>();
        List<UserCouponsVO> userCouponsVOS = new ArrayList<>();
        userCouponsPOPage.getRecords().forEach(couponPO -> {
            UserCouponsVO userCouponsVO = new UserCouponsVO();
            BeanUtils.copyProperties(couponPO,userCouponsVO);
            userCouponsVOS.add(userCouponsVO);
        });
        userCouponsVOPageResult.setObjects(userCouponsVOS);
        userCouponsVOPageResult.setPageNo((int)userCouponsPOPage.getCurrent());
        userCouponsVOPageResult.setPageSize((int)userCouponsPOPage.getSize());
        userCouponsVOPageResult.setTotal(userCouponsPOPage.getTotal());
        return userCouponsVOPageResult;
    }

    @Override
    @Cacheable(value = "userCouponsDetail", key = "#query.userId + '_' + #query.couponCode")
    public UserCouponsVO receiveDetail(UserCouponCodeQuery query) throws BusinessException {
        log.debug("查看优惠券码的二维码图片业务：userCouponCodeQuery={}",query);
        //身份校验
//        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
//        Asserts.isTrue(userPrinciple==null,new BusinessException("401","身份校验失败"));
        // 如果缓存中没有，再到数据库中查询
        UserCouponsPO userCouponsPO = userCouponsRepository.receiveDetail(query.getUserId(),query.getCouponCode());
        Asserts.isTrue(userCouponsPO==null,new BusinessException("297","优惠券不存在"));
        //生成二维码图片 内容：userId_couponCode
        AttachQRParam attachQRParam = new AttachQRParam();
        attachQRParam.setContent(query.getUserId()+"_"+query.getCouponCode());
        AttachQrDTO attachQrDTO = new AttachQrDTO();
        try {
            attachQrDTO = attachApi.generateQrCode(attachQRParam);
        }catch (Exception ex){
            log.error("生成二维码失败：ex={}",ex.getMessage());
        }
        //PO转VO
        UserCouponsVO userCouponsVO = new UserCouponsVO();
        BeanUtils.copyProperties(userCouponsPO, userCouponsVO);
        userCouponsVO.setCouponUrl(attachQrDTO.getUrl());
        return userCouponsVO;
    }

    @Override
    public void useReceive(Integer userId, String couponCode, String orderNo) throws BusinessException {
        log.debug("优惠券核销业务：userId={},couponCode={}", userId, couponCode);
        //身份验证
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("401","身份校验失败"));
        //优惠券是否存在
        UserCouponsPO userCouponsPO = userCouponsRepository.receiveDetail(userId,couponCode);
        Asserts.isTrue(userCouponsPO==null,new BusinessException("297","优惠券不存在"));
        //优惠券状态是否为未使用
        Asserts.isTrue(userCouponsPO.getStatus()!= UserCouponsStatusEnum.NOT_USE.getCode(),new BusinessException("297","优惠券已被使用"));
        //进行核销
        userCouponsPO.setStatus(UserCouponsStatusEnum.USED.getCode());
        userCouponsPO.setOrderNo(orderNo);
        userCouponsPO.setUsedTime(new Date());
        userCouponsRepository.updateUserCoupons(userCouponsPO);
    }

    @Override
    public void delete(Integer id) throws BusinessException {
        log.debug("删除优惠券业务：couponId={}",id);
        //身份校验
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("401","身份校验失败"));
        //校验当前用户是否具有删除此优惠券的权限
        AdminDto admin = userApi.getAdminById(userPrinciple.getId());
        Asserts.isTrue(admin.getAccountType()!=1,new BusinessException("297","无操作权限"));
        CouponPO couponPO = couponRepository.getCouponById(id);
        Asserts.isTrue(couponPO==null,new BusinessException("297","优惠券不存在"));
        Asserts.isTrue(admin.getBusinessId()!=couponPO.getBusinessId(),new BusinessException("297","无操作权限"));
        //删除优惠券
        couponRepository.deleteCoupon(id);
        couponCodeRepository.deleteByCouponId(id);
        stockRepository.deleteByCouponId(id);
    }
}
